package com.example.workflow.service.Impl;


import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.example.workflow.common.R;
import com.example.workflow.dto.DeptFormDto;
import com.example.workflow.entity.Dept;
import com.example.workflow.entity.DeptHierarchy;
import com.example.workflow.entity.Employee;
import com.example.workflow.entity.EmployeePosition;
import com.example.workflow.entity.Position;
import com.example.workflow.mapper.DeptHierarchyMapper;
import com.example.workflow.mapper.DeptMapper;
import com.example.workflow.service.DeptHierarchyService;
import com.example.workflow.service.DeptService;
import com.example.workflow.service.EmployeePositionService;
import com.example.workflow.service.EmployeeService;
import com.example.workflow.service.PositionService;
import com.example.workflow.vo.DeptVo;
import com.example.workflow.vo.EmployeeVo;
import com.example.workflow.vo.PostListVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 部门 服务实现类
 * </p>
 *
 * @author 黄历
 * @since 2024-03-12
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept>
        implements DeptService {

    private final DeptHierarchyMapper deptHierarchyMapper;

    private final DeptHierarchyService deptHierarchyService;

    private final PositionService positionService;

    private final EmployeePositionService employeePositionService;
    ;

    @Override
    public List<DeptVo> getDeptTree(Integer id) {
        if (id == 5) id = 4;
        //查询到的部门列表
        List<Dept> dept = Db.lambdaQuery(Dept.class)
                .le(id != null,Dept::getLevel,id)
                .list();
        //初始化部门树列表
        List<DeptVo> deptVos = BeanUtil.copyToList(dept, DeptVo.class);

        Map<Long,DeptVo> deptMap = new HashMap<>();
        for (DeptVo deptVo : deptVos) {
            deptVo.setChildren(new ArrayList<>()); // 初始化子部门列表
            deptMap.put(deptVo.getId(),deptVo);
        }

        //获取部门层级关系
        List<DeptHierarchy> deptHierarchyList = Db.lambdaQuery(DeptHierarchy.class).list();

        Set<Long> deptHierarchySet = new HashSet<>();

        for(DeptHierarchy dh : deptHierarchyList) {
            deptHierarchySet.add(dh.getChildId());

            DeptVo parentDept = deptMap.get(dh.getParentId());
            DeptVo childDept = deptMap.get(dh.getChildId());

            if (parentDept != null && childDept != null) {
                parentDept.getChildren().add(childDept);
            }
        }

        // 找到根部门,对deptList过滤
        List<DeptVo> rootDepths = new ArrayList<>();
        for (DeptVo deptVo : deptVos) {
            if (!deptHierarchySet.contains(deptVo.getId())) {
                // 如果部门没有父部门，则该部门为根部门
                rootDepths.add(deptVo);
            }
        }

        return rootDepths;
    }

    /**
     * 增加部门  操作部门表  部门继承表
     * deptFormDto 部门表单信息
     */
    @Override
    public Boolean addDept(DeptFormDto deptFormDto) {
        Dept dept = new Dept();
        BeanUtil.copyProperties(deptFormDto, dept, "parentId", "parentLevel", "level");
        int level = deptFormDto.getParentLevel() + 1;
        dept.setLevel(level);
        // 查询同级部门是否存在同名的 where level = ? and  dept_name = ?
        Dept one = lambdaQuery().eq(Dept::getLevel, level)
                .eq(Dept::getDeptName, dept.getDeptName()).one();
        if (one == null) {
            save(dept);
            log.info("========================");
            log.info("添加部门，{}", dept);
            log.info("========================");
        } else {
            log.info("同级部门存在同名");
            return false;
        }

        DeptHierarchy deptHierarchy = new DeptHierarchy();

        deptHierarchy.setParentId(deptFormDto.getParentId());
        deptHierarchy.setChildId(dept.getId());
        Db.save(deptHierarchy);
        // 新增成功
        return true;
    }

    /**
     * 删除部门同时需要删除树形结构的关系   操作 部门表， 员工表， 部门继承表  员工岗位表
     * ids  部门id
     */
    @Transactional
    @Override
    public Boolean deleteDept(List<Long> ids) {

        List<Boolean> collect = ids.stream().map(id -> {
            //首先根据部门id 去岗位表查询岗位id
            List<Position> positions = positionService.lambdaQuery().eq(Position::getDeptId, id).list();
            boolean flag = false;
            for (Position position : positions) {
                Long positionId = position.getId();
                //然后再根据岗位id去员工岗位表中查询是否有数据
                List<EmployeePosition> employeePositions = employeePositionService.lambdaQuery().eq(EmployeePosition::getPositionId, positionId).list();
                if (employeePositions != null) {
                    flag = true;
                    break;
                }
            }
            //该部门下有人
            if (!flag) {
                return false;
            }
            // 然后删除部门继承表的记录 删除的部门为字节点  where  child_id = ?
            LambdaQueryWrapper<DeptHierarchy> deptHierarchyLambdaQueryWrapper = new LambdaQueryWrapper<>();
            deptHierarchyLambdaQueryWrapper.eq(DeptHierarchy::getChildId, id);
            deptHierarchyService.remove(deptHierarchyLambdaQueryWrapper);
            // 最后从部门表删除记录
            removeById(id);
            return true;
        }).collect(Collectors.toList());

        for (boolean b : collect) {
            if (!b) {
                return false;
            }
        }
        return true;
    }

    @Override
    public DeptFormDto getDeptInfo(Long id) {
        //要查询的部门信息
        Dept dept = Db.lambdaQuery(Dept.class).eq(Dept::getId,id).one();
        //要查询的部门的父部门id
        Long parentId = Db.lambdaQuery(DeptHierarchy.class).eq(DeptHierarchy::getChildId,id).one().getParentId();
        //要查询的部门的父部门等级
        Integer parentLevel = Db.lambdaQuery(Dept.class).eq(Dept::getId,parentId).one().getLevel();

        DeptFormDto deptFormDto = BeanUtil.copyProperties(dept,DeptFormDto.class);
        deptFormDto.setParentId(parentId);
        deptFormDto.setParentLevel(parentLevel);

        return  deptFormDto;
    }


    /**
     * 更新部门信息  操作 部门表
     * deptFormDto 部门表单
     * id 更新部门id
     */
    @Override
    public Boolean updateDept(DeptFormDto deptFormDto, Long id) {
        //当前部门等级
        Integer level = deptFormDto.getLevel();
        String deptName = deptFormDto.getDeptName();
        //父部门级别只能和更新前父部门级别相同，例如4级部门的父部门级别为三级更新后也只能为三级
        if(deptFormDto.getParentLevel() + 1 != level) return  false;
        if (level >= 5) {
            log.error("更新部门级别 > 4");
            return false;
        }
        // 去部门表查询同级表是否存在同名
        Dept one = this.lambdaQuery().eq(Dept::getLevel, level)
                .eq(Dept::getDeptName, deptName).one();
        if (one != null) {
            log.error("存在同级同名");
        } else {
            Dept dept = new Dept();
            BeanUtil.copyProperties(deptFormDto, dept);
            dept.setId(id);
            this.updateById(dept);
        }

        LambdaUpdateWrapper<DeptHierarchy> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper
                .eq(DeptHierarchy::getChildId, id)
                .set(DeptHierarchy::getParentId, deptFormDto.getParentId());
        deptHierarchyMapper.update(null, lambdaUpdateWrapper);

        return true;
    }

    /**
     * 获取该部门的全部岗位  操作  岗位表
     * id 部门id
     */

    @Override
    public R getAllPositionsById(Long id) {
        List<Position> positions = positionService.lambdaQuery().eq(Position::getDeptId, id).list();
        if (positions == null || positions.isEmpty()) {
            return R.error("该部门没有岗位");
        }
        List<PostListVo> postListVos = BeanUtil.copyToList(positions, PostListVo.class);
        return R.success(postListVos);
    }

    /**
     * 查询出这个岗位的全部上级  操作  岗位表  部门继承表
     * id  岗位id
     * return 上级与本机部门id 允许null
     */

    @Override
    public R<List<Long>> getAllSuperiorDept(Long id) {
        // 先从岗位表查询出部门id
        Position position = positionService.getById(id);
        if (position == null) {
            return R.error("岗位没有所对应的部门");
        }
        Long deptId = position.getDeptId();
        ArrayList<Long> result = new ArrayList<>(4);
        // 最高四层部门 所以查四次部门继承表
        DeptHierarchy three = deptHierarchyService.lambdaQuery().eq(DeptHierarchy::getChildId, deptId).one();
        if (three == null) {
            result.add(null);
            result.add(null);
            result.add(null);
            result.add(deptId);
        }
        DeptHierarchy two = deptHierarchyService.lambdaQuery().eq(DeptHierarchy::getChildId, three.getChildId()).one();
        if (two == null) {
            result.add(null);
            result.add(null);
            result.add(three.getChildId());
            result.add(deptId);
        }
        DeptHierarchy one = deptHierarchyService.lambdaQuery().eq(DeptHierarchy::getChildId, two.getChildId()).one();
        if (one == null) {
            result.add(null);
            result.add(two.getChildId());
            result.add(three.getChildId());
            result.add(deptId);
        }

        result.add(one.getChildId());
        result.add(two.getChildId());
        result.add(three.getChildId());
        result.add(deptId);


        return R.success(result);
    }


    /**
     * 获取所有二级ceo、所有三级ceo、所有四级ceo的列表的接口  操作 岗位表， 员工岗位表， 员工表
     * type = 4, dept_id = 1
     * return  员工id, 员工name ， ceoLevel
     */

    @Override
    public R getAllCeo() {
        ArrayList<EmployeeVo> employeeVos = new ArrayList<>();
        // 先从岗位表中查询出ceo dept_id = 1 根据type分组
        Map<Integer, List<Position>> collect = positionService.lambdaQuery().eq(Position::getDeptId, 1).list().stream()
                .collect(Collectors.groupingBy(Position::getType));
        // 再查询出它们的岗位id, 去员工岗位表查询员工id  只有四次循环
        collect.forEach((ceoLevel, positions) -> positions.forEach(position -> {
            Long positionId = position.getId();
            // 各级ceo只能有一位所以只能查出一个
            EmployeePosition employeePosition = employeePositionService.lambdaQuery().eq(EmployeePosition::getPositionId, positionId).one();
            Long empId = employeePosition.getEmpId();
            // 根据员工id  查询员工表中的员工姓名
            Employee employee = Db.lambdaQuery(Employee.class).eq(Employee::getId,empId).one();
            EmployeeVo employeeVo = new EmployeeVo();
            employeeVo.setId(empId);
            employeeVo.setName(employee.getName());
            employeeVo.setCeoLevel(ceoLevel);
            employeeVos.add(employeeVo);
        }));

        return R.success(employeeVos);
    }
}
